/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.appspot.ittrick.drive.trick.cell;

import com.appspot.ittrick.drive.trick.DriveTrick;
import com.appspot.ittrick.drive.trick.api.DriveAPIService;
import com.appspot.ittrick.drive.trick.controller.MainController;
import com.appspot.ittrick.drive.trick.custom.FolderTreeItem;
import com.appspot.ittrick.drive.trick.task.FileMoveTask;
import com.google.api.services.drive.model.File;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;

/**
 *
 * @author takahara
 */
public class FolderTreeCell extends TreeCell<File> {

    private TextField textField;
    private final ContextMenu contextMenu = new ContextMenu();
    private final ContextMenu rootContextMenu = new ContextMenu();

    /**
     * コンストラクタ
     */
    public FolderTreeCell() {
        
        MenuItem addFolderMenuItem = new MenuItem("フォルダの追加");
        MenuItem changeNameMenuItem = new MenuItem("フォルダ名の変更");
        MenuItem deleteFolderMenuItem = new MenuItem("削除");
        MenuItem refreshmentMenuItem = new MenuItem("更新");
        
        ImageView addFolderMenuItemIcon = new ImageView(DriveTrick.class.getResource("images/context_menu/add.png").toString());
        addFolderMenuItemIcon.setFitHeight(17);
        addFolderMenuItemIcon.setPreserveRatio(true);
        addFolderMenuItem.setGraphic(addFolderMenuItemIcon);
        
        ImageView refreshmentMenuItemIcon = new ImageView(DriveTrick.class.getResource("images/context_menu/refresh.png").toString());
        refreshmentMenuItemIcon.setFitHeight(17);
        refreshmentMenuItemIcon.setPreserveRatio(true);
        refreshmentMenuItem.setGraphic(refreshmentMenuItemIcon);
        
        ImageView deleteFileMenuItemIcon = new ImageView(DriveTrick.class.getResource("images/context_menu/delete.png").toString());
        deleteFileMenuItemIcon.setFitHeight(17);
        deleteFileMenuItemIcon.setPreserveRatio(true);
        deleteFolderMenuItem.setGraphic(deleteFileMenuItemIcon);
        
        rootContextMenu.getItems().addAll(refreshmentMenuItem, new SeparatorMenuItem(), addFolderMenuItem);
        contextMenu.getItems().addAll(refreshmentMenuItem, new SeparatorMenuItem(), addFolderMenuItem, changeNameMenuItem, new SeparatorMenuItem(), deleteFolderMenuItem);


        // フォルダ追加メニューイベント
        addFolderMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                final DriveAPIService driveService = MainController.getInstance().getDriveService();
                
                File file = driveService.insertFolder(
                                    getTreeItem().getValue().getId(), 
                                    "新しいフォルダ");
                
                // フォルダが開いてない場合はOPENする
                if (!getTreeItem().expandedProperty().get()) {
                    getTreeItem().setExpanded(true);
                }

                // TreeViewにフォルダを追加
                FolderTreeItem newTreeItem = new FolderTreeItem(file);
                getTreeItem().getChildren().add(newTreeItem);
                getTreeView().getSelectionModel().select(newTreeItem);
            }
        });


        // 名前変更メニューイベント
        changeNameMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                // treeView を変更可能に設定し、変更開始する
                getTreeView().editableProperty().set(true);
                startEdit();
            }
        });


        // フォルダ削除メニューイベント
        deleteFolderMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                try {
                    DriveAPIService driveService = MainController.getInstance().getDriveService();
                    driveService.deleteFile(getItem());
                    getTreeItem().getParent().getChildren().remove(getTreeItem());
                } catch (IOException ex) {
                    Logger.getLogger(FolderTreeCell.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        
        
        // 更新メニューイベント
        refreshmentMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                MainController.getInstance().laodFolderListTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
                    @Override
                    public void handle(WorkerStateEvent t) {

                        List<FolderTreeItem> folderList = (List<FolderTreeItem>) t.getSource().getValue();
                        getTreeItem().getChildren().setAll(folderList);
                        
                        MainController.getInstance().folderTreeView.getSelectionModel().select(getTreeItem());
                    }
                });

                MainController.getInstance().laodFolderListTask.run(getItem().getId());
            }
        });
    }

    @Override
    public void startEdit() {
        super.startEdit();

        if (textField == null) {
            createTextField();
        }
        setText(null);
        setGraphic(textField);
        textField.selectAll();
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();
        setText(getItem().getTitle());
        setGraphic(getTreeItem().getGraphic());

        // treeView を変更不可に設定する
        getTreeView().editableProperty().set(false);
    }

    @Override
    public void commitEdit(File file) {
        try {
            super.commitEdit(file);

            DriveAPIService driveService = MainController.getInstance().getDriveService();
            driveService.updateFile(file.getId(), file);

            // treeView を変更不可に設定する
            getTreeView().editableProperty().set(false);

        } catch (IOException ex) {
            Logger.getLogger(FolderTreeCell.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * セル更新
     *
     * @param item
     * @param empty
     */
    @Override
    public void updateItem(final File item, boolean empty) {
        super.updateItem(item, empty);

        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            super.setText(item.getTitle());
            setGraphic(new ImageView(new Image(item.getIconLink())));

            final TreeView treeView = getTreeView();
            final TreeItem treeItem = getTreeItem();

            if (!getTreeItem().isLeaf() && getTreeItem().getParent() != null) {
                setContextMenu(contextMenu);
            }else {
                setContextMenu(rootContextMenu);
            }

            // ダブルクリックイベント
            this.setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {

                    if (event.getClickCount() == 2) {
                        File file = getItem();
                        treeItem.setExpanded(true);
                        treeView.getSelectionModel().select(treeItem);

                        MainController controller = (MainController) treeView.getScene().getRoot();
                        controller.loadFileListTask.loadFilesByFolderId(file);
                        
                        
                    }
                }
            });
            
            // ドロップイベント
            initDropEvent();

        }
    }

    private void createTextField() {
        final File file = getItem();
        textField = new TextField(file.getTitle());
        textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent t) {
                if (t.getCode() == KeyCode.ENTER) {
                    file.setTitle(textField.getText());
                    commitEdit(file);
                } else if (t.getCode() == KeyCode.ESCAPE) {
                    cancelEdit();
                }
            }
        });
    }
    
    
    private void initDropEvent() {
        // ---------------------------------------------------------------------
        // マウス転入
        // ---------------------------------------------------------------------
        this.setOnDragEntered(
                new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
                TreeCell treeCell = (TreeCell)event.getTarget();
                
                if (!treeCell.isSelected()) {
                    treeCell.setStyle("-fx-background-color: steelblue;");
                }
                event.consume();
            }
        });
        
        // ---------------------------------------------------------------------
        // マウス転出
        // ---------------------------------------------------------------------
        this.setOnDragExited(
                new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
                TreeCell treeCell = (TreeCell)event.getTarget();
                if (!treeCell.isSelected()) {
                    treeCell.setStyle("-fx-background-color: rgb(209, 216, 224);");
                }
                event.consume();
            }
        });
        
        // ---------------------------------------------------------------------
        // ドラッグ中
        // ---------------------------------------------------------------------
        this.setOnDragOver(
                new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
                event.acceptTransferModes(TransferMode.MOVE);
                event.consume();
            }
        });

        // ---------------------------------------------------------------------
        // ドラッグ実行
        // ---------------------------------------------------------------------
        this.setOnDragDropped(
                new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
                TreeCell targetCell = (TreeCell)event.getSource();

                File parentFile = (File)targetCell.getItem();
                Dragboard db = event.getDragboard();
                
                if (db.hasString()) {
                    String fileId = db.getString();

                    FileMoveTask task = new FileMoveTask();
                    task.run(fileId, parentFile.getId());
                    
                    ClipboardContent clipd = new ClipboardContent();
                    clipd.putString("DragSuccess");
                    db.setContent(clipd);
                }
                
                event.setDropCompleted(true);
                event.consume();
            }
        });
    }
}
